/*
 * Copyright (C) 2018 C-SKY Microsystems Co., Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IPC_INTERNAL_H
#define IPC_INTERNAL_H

#include "ipcm.h"
#include "channel_mailbox.h"
#include "adapter_event.h"
#include <aos/list.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef linux
#   define aos_mutex_new(mutex)        pthread_mutex_init(mutex, NULL)
#   define aos_mutex_lock(mutex, n)    pthread_mutex_lock(mutex)
#   define aos_mutex_unlock(mutex)     pthread_mutex_unlock(mutex)
#   define aos_sem_new(sem, n)         sem_init(sem, 0, n)
static int aos_sem_wait(aos_sem_t *sem, int timeout_ms) {
    if (timeout_ms >= 0) {
        struct timespec abs_timeout;
        abs_timeout.tv_sec  = timeout_ms / 1000;
        abs_timeout.tv_nsec = (timeout_ms % 1000) * 1000;

        return sem_timedwait(sem, &abs_timeout);
    } else {
        return sem_wait(sem);
    }
}

#   define aos_sem_signal(sem)         sem_post(sem)
#   define aos_sem_free(sem)           sem_destroy(sem)
#   define aos_task_new_ext(task, n, fn, arg, size, prio)  pthread_create(task, NULL, fn, arg)
#   define aos_task_exit(n) pthread_exit(n)
#endif


typedef struct message_msg {
    uint8_t         flag;            /** flag for MESSAGE_SYNC and MESSAGE_ACK */
    uint8_t         service_id;      /** service id for the service want to comtunicate */
    uint16_t        command;         /** command id the service provide */
    aos_sem_t       sem;             /** sem id for SYNC MESSAGE */
    uint32_t        id;              /** message id */
    int             len;             /** message len */
    void           *data;            /** message data */
}ipc_msg_t;


/* ipc data format */
typedef struct {
    void* param_in;
    void* param_out;
} ipcm_data_t;


struct ipc {
    slist_t next;
    channel_t *ch;            /** channel */
    slist_t    service_list;  /** service list */

    uint32_t   des_cpu_id;    /** destination CPU ID*/

    aos_task_t thread;        /** thread ID */
    aos_event_t evt;          /** enevt */
    aos_mutex_t mutex;        /** mutex samephore */
    void *priv;               /** Private data */
};

typedef struct ipc ipcm_t;
typedef void (*ipcm_process_t)(ipcm_t *ipcm, ipc_msg_t *msg, void *priv);

typedef struct service {
     int id;                 /* service ID*/
     ipcm_process_t process;  /* callback functoin */
     void * priv;            /* private data */
     slist_t next;       
} service_t;


#ifdef __cplusplus
}
#endif

#endif
